#define WIN32_LEAN_AND_MEAN
// Need to link with Ws2_32.lib
#pragma comment(lib, "ws2_32.lib")
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iostream>
#include <event2/event.h>
#include "local_server.h"
#include "event_handler.h"
#include "default_handle_http_request.h"
using namespace std;

LocalServer::~LocalServer()
{
    DoClose();
}

bool LocalServer::Init()
{
    WORD wVersionRequested;
    WSADATA wsaData;
    int err;

    wVersionRequested = MAKEWORD(2, 2);
    err = WSAStartup(wVersionRequested, &wsaData);

    if (err != 0)
    {
        /* Tell the user that we could not find a usable */
        /* WinSock DLL.                                  */
        cout << "WSAStartup failed with error: " << wVersionRequested << endl;
        return false;
    }

    if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
    {
        WSACleanup();
        cout << "WSAStartup failed!couldn't find a usable WinSock DLL" << endl;
        return false;
    }

    //create dispatcher and http handler
    m_pEvBase = event_base_new();
    if (nullptr == m_pEvBase)
    {
        cout << ("couldn't open event base!") << endl;
        return false;
    }

    m_pEvHttp = evhttp_new(m_pEvBase);

    //bind ip and listening the port
    if (evhttp_bind_socket(m_pEvHttp, BIND_HOST, m_port) != 0)
    {
        cout << "evhttp_bind_socket failed" << endl;
    }



    if (!m_pEvHandler)
    {
        m_pEvHandler = new EventHandler;
        m_pEvHandler->HandleRequest = default_handle_http_request;
    }

    //set handler
    evhttp_set_gencb(m_pEvHttp, m_pEvHandler->HandleRequest, NULL);

    m_inited = true;
    return m_inited;
}

void LocalServer::DoOpen()
{
    if (!m_inited)
    {
        cout << "LibEvServer stared failed!" << endl;
        exit(1);
    }

    //loop 
    event_base_dispatch(m_pEvBase);

}

void LocalServer::DoClose()
{
    if (m_pEvBase)
    {
        event_base_loopexit(m_pEvBase, nullptr);
        event_base_free(m_pEvBase);
    }
    if (m_pEvHttp)
    {
        evhttp_free(m_pEvHttp);
    }
    if (m_pEvHandler)
    {
        delete m_pEvHandler;
    }

    WSACleanup();
}

void LocalServer::SetEventHandler(EventHandler* handler)
{
	m_pEvHandler = handler;
}

void LocalServer::Start()
{
    DoOpen();
}


void LocalServer::Stop()
{
    DoClose();
}
